/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sessions;

import entities.NotificationType;
import entities.UUser;
import init.Config;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

/**
 *
 * @author Antoine Boulinguez et Shyn-Yuan Cheng
 */
@Stateless
@LocalBean
public class UserManager {

    @EJB
    private NotificationManager notificationManager;
    @PersistenceContext(unitName = "ProjetStreamingBoulinguezCheng-ejbPU")
    private EntityManager em;

    public void createTestUsers() {
        String defaultAvatar = Config.USER_DEFAULT_AVATAR.replaceAll("\\\\", "/");

        createUser(defaultAvatar, "cs800350@etu.unice.fr", "Shyn-Yuan", "Cheng", "azerty");
        createUser(defaultAvatar, "ba800690@etu.unice.fr", "Antoine", "Boulinguez", "azerty");
        createUser(defaultAvatar, "toto@titi.fr", "titi", "toto", "azerty");
        createUser(defaultAvatar, "tata@lulu.fr", "tata", "lulu", "azerty");

        // Get data from xml
        createUsersFromXML();

    }

    public void createUsersFromXML() {
        String defaultAvatar = Config.USER_DEFAULT_AVATAR.replaceAll("\\\\", "/");
        // Parsing via SAX
        Document document;
        Element racine;
        SAXBuilder sxb = new SAXBuilder();
        try {
            File xmlUserDataFile = new File(this.getClass().getResource("/resources/user_data.xml").getFile());
            document = sxb.build(xmlUserDataFile);
            System.out.println("PATH : " + xmlUserDataFile.getAbsolutePath());
            racine = document.getRootElement();
            List userList = racine.getChildren("user");

            //On crée un Iterator sur notre liste
            Iterator i = userList.iterator();
            while (i.hasNext()) {
                Element currentUser = (Element)i.next();
                String email = currentUser.getChild("email").getText();
                String firstname = currentUser.getChild("firstname").getText();
                String lastname = currentUser.getChild("lastname").getText();
                
                createUser(defaultAvatar, email, firstname, lastname, "azerty");
            }
        } catch (Exception e) {}


    }

    public boolean existEmail(String email) {
        Query q = em.createQuery("SELECT COUNT (u.email) FROM UUser u WHERE u.email=:email");
        q.setParameter("email", email);
        Object result = q.getSingleResult();
        Long count = (Long) result;

        if (count.intValue() == 0) {
            return false;
        } else {
            return true;
        }
    }

    public UUser createUser(String avatar, String email, String firstname, String lastname, String password) {
        UUser existUser = getUser(email);

        if (existUser == null) {
            password = getEncryptedPassword(password);
            UUser user = new UUser(avatar, email, firstname, lastname, password);
            persist(user);

            return user;
        } else {
            return existUser;
        }
    }

    public boolean addFriend(UUser user, UUser friend) {
        if (user.addFriend(friend) && friend.addFriend(user)) {
            update(user);
            update(friend);

            // Create a notification for the friend
            String description = notificationManager.getFriendNotificationDescription(user);
            notificationManager.createNotification(description, NotificationType.FRIEND, user, friend);

            return true;
        } else {
            return false;
        }
    }

    public boolean removeFriend(UUser user, UUser friend) {
        if (user.removeFriend(friend) && friend.removeFriend(user)) {
            update(user);
            update(friend);

            return true;
        } else {
            return false;
        }
    }

    public UUser getUser(Long id) {
        Query query = em.createNamedQuery("UUser.getById");
        query.setParameter("id", id);

        try {
            Object result = query.getSingleResult();
            return (UUser) result;
        } catch (NoResultException e) {
            return null;
        }
    }

    public UUser getUser(String email) {
        Query query = em.createNamedQuery("UUser.getByEmail");
        query.setParameter("email", email);

        try {
            Object result = query.getSingleResult();
            return (UUser) result;
        } catch (NoResultException e) {
            return null;
        }
    }

    public UUser getUser(String email, String password) {
        password = getEncryptedPassword(password);

        Query query = em.createNamedQuery("UUser.login");
        query.setParameter("email", email);
        query.setParameter("password", password);

        try {
            Object result = query.getSingleResult();
            return (UUser) result;
        } catch (NoResultException e) {
            return null;
        }
    }

    public List<UUser> getUserLike(Long currentUserId, String str) {
        Query query = em.createNamedQuery("UUser.getLike");
        query.setParameter("str", str + "%");
        query.setParameter("id", currentUserId);

        try {
            return query.getResultList();
        } catch (NoResultException e) {
            return null;
        }
    }

    public String getEncryptedPassword(String password) {
        MessageDigest md;
        String result = "";
        try {
            md = MessageDigest.getInstance("SHA-256");

            md.update(password.getBytes());

            byte byteData[] = md.digest();

            //convert the byte to hex format method 1
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }

            //convert the byte to hex format method 2
            StringBuilder hexString = new StringBuilder();
            for (int i = 0; i < byteData.length; i++) {
                String hex = Integer.toHexString(0xff & byteData[i]);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            result = hexString.toString();

        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(UserManager.class.getName()).log(Level.SEVERE, null, ex);
        }

        return result;
    }

    public void update(Object object) {
        em.merge(object);
    }

    public void persist(Object object) {
        em.persist(object);
    }

    public void persist1(Object object) {
        em.persist(object);
    }
}
